﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace DownloadBook {
    class DownloadContent {
        private List<Content> originContentList;
        private string directory;
        private string originUrl;
        private UpdateMessage updateMessage;
        private int originCount;
        private int completeCount;
        private Action m_Callback;
        private List<Content> contentList;
        private int m_MaxThreadCount;
        private bool needStop, stoping;

        public DownloadContent(string directory, string originUrl, List<Content> contentList, int maxThreadCount, UpdateMessage updateMessage, Action callback) {
            this.directory = directory;
            this.originUrl = originUrl;
            this.updateMessage = updateMessage;
            this.originContentList = new List<Content>(contentList);
            this.m_MaxThreadCount = maxThreadCount;
            originCount = this.originContentList.Count;
            this.m_Callback = callback;
        }


        public delegate void UpdateMessage(string msg);
        private List<Thread> m_ThreadList = new List<Thread>();
        public void Start() {
            completeCount = 0;
            this.DoStart();
        }
        public void Stop() {
            needStop = true;
        }
        private void ReStart() {
            this.DoStart();
        }
        private void DoStart() {
            lock (this) {
                if (contentList == null) {
                    contentList = new List<Content>(originContentList);
                } else {
                    contentList.Clear();
                    contentList.AddRange(originContentList);
                }
            }
            lock (m_ThreadList) {
                for (int i = 0; i < m_MaxThreadCount && i < originContentList.Count; i++) {
                    ThreadPool.QueueUserWorkItem(Work);
                }
            }
        }

        private void Work(Object obj) {
            bool needWork = true;
            for (; needWork; ) {
                if (needStop) {//如果要求停止下载
                    if (!stoping) {
                        stoping = true;

                        string msg = "用户要求停止下载";
                        Console.WriteLine(msg);
                        updateMessage(msg);
                        if (m_Callback != null) {
                            m_Callback();
                        }
                    }
                    break;
                }
                Content content = null;
                lock (this) {
                    lock (contentList) {
                        if(contentList.Count > 0) {
                            content = contentList[0];
                            contentList.RemoveAt(0);
                        }
                    }
                }

                if (content == null) {
                    bool lastThreadComplete = false;
                    lock (m_ThreadList) {
                        m_ThreadList.Remove(Thread.CurrentThread);
                        if(m_ThreadList.Count == 0) {
                            lastThreadComplete = true;
                        }
                    }
                    if (lastThreadComplete) {
                        try {
                            string[] files = Directory.GetFiles(directory);
                            if (files.Length < originContentList.Count) {//如果有文件还未下载下来
                                this.ReStart();//重新开始
                            } else {
                                string msg = "下载任务已经结束";
                                Console.WriteLine(msg);
                                updateMessage(msg);
                                if (m_Callback != null) {
                                    m_Callback();
                                }
                            }
                        }catch(Exception) {
                            this.ReStart();
                        }
                    }
                    needWork = false;
                    break;
                } else {
                    string url = content.url;

                    string filePath = Path.Combine(directory, content.GetFileName());


                    if (!content.downloadComplete && !content.downloading) {//如果还未完成、也不是在下载中的，才有必要继续
                        string msg;
                        if (File.Exists(filePath)) {//如果文件已经存在了
                            ++completeCount;
                            msg = string.Format("{0}/{1} 忽略已经存在的章节文件：{2}", completeCount, originCount, content.title); ;
                            content.downloadComplete = true;
                        } else {//如果文件还未存在
                            content.downloading = true;
                            string html = HttpGet.httpGet(url, originUrl);
                            if (!string.IsNullOrEmpty(html)) {
                                if (!Directory.Exists(directory)) {
                                    Directory.CreateDirectory(directory);
                                }
                                lock (this) {
                                    byte[] buffer = Encoding.Default.GetBytes(html);
                                    File.WriteAllBytes(filePath, buffer);
                                }
                                content.downloadComplete = true;
                                ++completeCount;
                            }

                            content.downloading = false;

                            msg = string.Format("{0}/{1} 下载中：{2}", completeCount, originCount, content.title);
                        }

                        Console.WriteLine(msg);
                        updateMessage(msg);
                    }
                }
            }
        }
    }
}
